package com.stone.inventory.sharding.id.intercepter;

import com.stone.inventory.sharding.helper.ShardingHelper;
import io.choerodon.mybatis.domain.EntityTable;
import io.choerodon.mybatis.helper.EntityHelper;
import io.choerodon.mybatis.helper.MapperTemplate;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;

import java.util.Properties;

/**
 * 主键生成拦截器, 根据配置的主键生成策略将主键注入到对应实体中
 *
 * @author Mr_wenpan@163.com
 */
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class MybatisShardingIdInterceptor implements Interceptor {

    private final ShardingHelper shardingHelper;

    public MybatisShardingIdInterceptor(ShardingHelper shardingHelper) {
        this.shardingHelper = shardingHelper;
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 获取MappedStatement
        MappedStatement statement = (MappedStatement) invocation.getArgs()[0];
        // sql类型是insert的时候才进行拦截
        if (SqlCommandType.INSERT.equals(statement.getSqlCommandType())) {
            // 获取表实体
            EntityTable table = EntityHelper.getTableByMapper(MapperTemplate.getMapperClassName(statement.getId()));
            // 通过表名判断是否属于分片表
            if (shardingHelper.isSharding(table.getName())) {
                Object parameter = invocation.getArgs()[1];
                // parameter 为待插入的实体对象
                shardingHelper.autoGeneratorKey(parameter);
            }
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {

        if (target instanceof Executor) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(Properties properties) {

    }

}
